#include "SyscallManager.h"

char reg[100] = {0}; /* yep */
int error_code;
int pid; /* The pid of the process that called the command. */
int death[10] = {0};

// Need to get regs, then set success code and result.

void create_p(){
	int* result = (int*)&reg[0];

	/* Get a unique PID. */
	int pid = getUniquePID();
	/* Initialize the registers. */
	int regs[3] = {0,0,0};
	/* Allocate a page table for the process. */
	int table_id = alloc_pt(2);

	process_control_block* new_pcb;

	/* If the page table is allocated succesully. */
	if(table_id >= 0)
	{
		new_pcb = create(pid, 1, 0, table_id, regs);
		/* If the process is created successfully. */
		if(new_pcb != NULL)
		{
			/* Write the result. */
			*result = 0;
			error_code = pid;
		}
		else
		{
			/* Deallocate the page table. */
			dealloc_pt(table_id);
			/* Write the failure code. */
			error_code = -1;
		}
	}
	else
	{
		/* Write the failure code. */
		error_code = -2;
	}
}

void priority_p(){
	process_control_block* pcb;
	int new_priority;
	int result;
	/* Search in the Ready Queue. */
	pcb = searchAll(pid);
	new_priority = pcb->regs[0];
	result = setPriority(pcb, new_priority);
	error_code = result;
}

void exit_p(){
	process_control_block* pcb;
	if(pid == -1){
		pcb = queues[2].head;
		if(pcb != NULL){
			eoLife();
			error_code = 0;
	    }
		else{
			error_code = -2;
		}
	}
	else if(searchAll(pid) != NULL){
		terminate(pid);
		error_code = 0;
	}
	else{
		error_code = -1;
	}
}

void status_p(){
	process_control_block* pcb;
	pcb = search(1,pid);
	if(pcb != NULL){
		error_code = 1;
		death[pcb->regs[0]] = 1;
	}
	else{
        pcb = search(2,pid);
		if(pcb != NULL){
			error_code = 2;
			death[pcb->regs[0]] = 2;
		}
		else{
			pcb = search(3,pid);
			if(search(3,pid) != NULL){
				error_code = 3;
				death[pcb->regs[0]] = 3;
			}
			else{
				error_code = -1;
				death[pcb->regs[0]] = -1;
			}
		}
	}
}

void open_i(){
	process_control_block* pcb;
	int i = 0;
	int set = 0;
	pcb = searchAll(pid);
	if(pcb != NULL){
		if(pcb->mailbox == -1){
			for(i = 0; i < 10; i++){
				 if(mailboxes[i].taken == -1){
					 mailboxes[i].taken = pid;
					 pcb->mailbox = i;
					 error_code = i;
					 set = 1;
					 break;
				 }
			 }
			if(set != 1){
				error_code = -1;
			}
		}
		else{
			error_code = -3;
		}
	}
	else{
		error_code = -2;
	}
}

void send_i(){
	process_control_block* pcb;
	int mailboxID;
	int blocking_code;
	int message;
	int receiver;
	int result;
	
	pcb = queues[2].head;
	mailboxID = pcb->regs[0];
	blocking_code = pcb->regs[1];
	message = pcb->regs[2];
	receiver = mailboxes[mailboxID].taken;

	if(searchAll(receiver) == NULL){
		mailboxes[mailboxID].taken = -1;
		error_code = -3;
	}
	else if(pcb->mailbox == -1){
		error_code = -4;
	}
	else{
		result = sendMessage(pcb->mailbox,mailboxID,message);
		if(blocking_code == 1){
			wait();
			if(result == 0){
				unwait(pid);
			}
		}		
		error_code = result;
	}
}

void recv_i(){
	process_control_block* pcb;
	int mailboxID;
	int blocking_code;
	int message_saver;
	
	pcb = queues[2].head;
	mailboxID = pcb->regs[0];
	blocking_code = pcb->regs[1];
	message_saver = pcb->regs[2];

	error_code = retrieveMessage(mailboxID);
	if(blocking_code == 1){
		wait();
	}
	if(error_code == 0){
		death[message_saver] = mailboxes[mailboxID].last_message.message;
		unwait(pid);
	}
}

void status_i(){
	process_control_block* pcb;
	pcb = searchAll(pid);
	if(pcb != NULL){
		error_code = isEmptyMailbox(pcb->mailbox);
		death[pcb->regs[1]] = error_code;
	}
	else{
        error_code = -1;
	}
}